package com.alphathink.BitMapUtil;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import android.graphics.Bitmap;
import android.os.Environment;

/**
 * 使用单例模式，来做磁盘缓存管理。
 * 
 * @author lrh
 *
 */
public class BitmapDiskCache {
	// 磁盘缓存目录
	public static String CACHE_DIR = Environment.getExternalStorageDirectory()
			+ File.separator + "lib" + File.separator + "pics";

	private static BitmapDiskCache diskCache = null;
	private static List<String> fileNames = null;
	// 缓存区最大值ֵ
	private int maxSize = 0;
	// 当前缓存区大小
	private int size = 0;

	public static BitmapDiskCache getInstance() {
		if (diskCache == null) {
			diskCache = new BitmapDiskCache(10 * 1024 * 1024);
		}
		return diskCache;
	}

	/**
	 * 构造函数
	 * 
	 * @param size
	 *            diskcache缓存区的大小。
	 */
	private BitmapDiskCache(int size) {
		this.maxSize = size;
		fileNames = new ArrayList<String>();
		initData();
	}

	/**
	 * 初始化相关信息
	 */
	private void initData() {
		File file = new File(CACHE_DIR);
		if (!file.exists()) {
			file.mkdirs();
		}
		File[] files = file.listFiles();
		if (files == null) {
			return;
		}
		int count = files.length;
		for (int i = 0; i < count; i++) {
			fileNames.add(files[i].getName());
		}
	}

	/**
	 * 根据文件名称获取为不存储文件。<br>
	 * 如果外部文件存在，则返回，并修改最后修改时间。否则返回null
	 * 
	 * @param name
	 * @return
	 */
	public File getCache(String name) {
		File file = new File(CACHE_DIR, name);
		if (file.exists()) {
			synchronized (file) {
				file.setLastModified(new Date().getTime());
			}
			return file;
		}
		return null;
	}

	/**
	 * 将一个bitmap对象存储至外部设备.并将本地文件纳入缓存管理。
	 * 
	 * @param bitmap
	 * @param name
	 * @return
	 */
	public boolean cacheBitmap(Bitmap bitmap, String name) {
		File file = new File(CACHE_DIR, name);
		try {
			FileOutputStream out = new FileOutputStream(file);
			bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
			out.flush();
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		fileNames.add(name);
		size += file.length();
		if (size >= maxSize) {
			// 删除最早修改的百分之十
			deleteOverFlow();
		}
		return true;
	}

	/**
	 * 从一个inputstream中把数据缓存进外部存储设备，并将此文件纳入文件管理中。
	 * 
	 * @param stream
	 * @param name
	 * @return
	 */
	public boolean cacheBitmapFromStream(InputStream stream, String name) {
		byte[] bs = new byte[1024 * 8];
		int length = 0;
		File file = new File(CACHE_DIR, name);
		try {
			FileOutputStream fileOutputStream = new FileOutputStream(file);
			while ((length = stream.read(bs)) != -1) {
				fileOutputStream.write(bs, 0, length);
			}
			stream.close();
			fileOutputStream.flush();
			fileOutputStream.close();
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		fileNames.add(name);
		size += file.length();
		if (size >= maxSize) {
			// 删除最早修改的百分之十
			deleteOverFlow();
		}
		return true;
	}

	/**
	 * 删除超过最大容量10%的图片。<br>
	 * 被删除的文件都是最早被修改的。也就是说很久没有被访问到了。
	 * 
	 * @return
	 */
	public boolean deleteOverFlow() {
		File file = new File(CACHE_DIR);
		File[] files = file.listFiles();
		List<File> list = new ArrayList<File>();
		int count = files.length;
		for (int i = 0; i < count; i++) {
			list.add(files[i]);
		}
		Collections.sort(list, new ImageFileComparator());
		File temp = null;
		count = files.length / 10 + 1;
		for (int i = 0; i < count; i++) {
			temp = list.remove(0);
			synchronized (temp) {
				size -= temp.length();
				fileNames.remove(temp.getName());
				temp.delete();
			}
		}
		return true;
	}
}
